use crate::{
    block_dev::BlockDevice,
    BlockID,
    BLOCK_SIZE,
};

use std::{
    fs::{File, OpenOptions}, 
    io::{Read, Seek, Write, SeekFrom, Result}
};

pub struct FileDisk {
    file: File,
}

impl FileDisk {
    pub fn new(path: &str) -> Result<Self> {
        let file = OpenOptions::new()
            .read(true)
            .write(true)
            .open(path)?;
        Ok(Self { file })
    }

    fn seek_block(&mut self, block_id: BlockID) {
        let byte_index = block_id as usize * BLOCK_SIZE;
        self.file.seek(SeekFrom::Start(byte_index as u64)).expect("FileDisk: seek failed!");
    }
}

impl BlockDevice for FileDisk {
    fn read_block(&mut self, block_id: BlockID, buf: &mut [u8]) {
        self.seek_block(block_id);
        self.file.read(buf).expect("FileDisk: read_block failed!");
    }

    fn write_block(&mut self, block_id: BlockID, buf: &[u8]) {
        self.seek_block(block_id);
        self.file.write(buf).expect("FileDisk: write_block failed!");
    }
}

